package com.ztgf.sys.service;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.ztgf.common.utils.StrUtils;
import com.ztgf.sys.common.config.YmlConfig;
import com.ztgf.sys.mapper.SysMenuMapper;
import com.ztgf.sys.mapper.SysRoleMenuRelationMapper;
import com.ztgf.sys.models.bo.SysMenuSaveBO;
import com.ztgf.sys.models.bo.SysRoleMenuRelationSaveBO;
import com.ztgf.sys.models.constant.SysConstant;
import com.ztgf.sys.models.dto.SysConfigDTO;
import com.ztgf.sys.models.dto.SysMenuDTO;
import com.ztgf.sys.models.enums.SYSCodeEnum;
import com.ztgf.sys.models.service.ISysMenuService;
import com.ztgf.sys.models.vo.SysMenuVO;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 菜单  服务实现类
 * </p>
 *
 * @author YUE123
 * @since 2020-05-26
 */
@DubboService
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenuDTO> implements ISysMenuService {
    @Resource
    private YmlConfig ymlConfig;

    @Autowired
    private SysMenuMapper sysMenuMapper;

    @Autowired
    private SysConfigServiceImpl sysConfigService;

    @Autowired
    private SysRoleServiceImpl sysRoleService;

    @Autowired
    private SysRoleMenuRelationMapper sysRoleMenuRelationMapper;

    @Autowired
    private SysRoleMenuRelationServiceImpl sysRoleMenuRelationService;

    /**
     * 获取所有的主菜单
     * @return
     */
    public List<SysMenuVO> getListMainMenu(){
        return baseMapper.selectMainMenu();
    }

  @Override
    public boolean add(SysMenuSaveBO sysMenuSaveBO) {
        SysMenuDTO sysMenuDTO = new SysMenuDTO();
        BeanUtils.copyProperties(sysMenuSaveBO,sysMenuDTO);
        Long id = ymlConfig.getPkId();
        sysMenuDTO.setId(id);

        if(sysMenuSaveBO.getWebType() == 0){//后台权限
            //关联和后台最大角色的关系
            SysRoleMenuRelationSaveBO sysRoleMenuRelationSaveBO = new SysRoleMenuRelationSaveBO();
            sysRoleMenuRelationSaveBO.setCode(sysMenuSaveBO.getCode());
            sysRoleMenuRelationSaveBO.setMenuId(id);
            sysRoleMenuRelationSaveBO.setRoleId(SysConstant.ADMIN_ID);
            sysRoleMenuRelationService.add(sysRoleMenuRelationSaveBO);
            return this.insert(sysMenuDTO);
        }

        return this.insert(sysMenuDTO);
    }

    /**
     * 删除菜单
     * @param menuId
     */
    public void deleteByMenuId(Long menuId){
        deleteRelationMenuInfo(menuId);
    }

    private void deleteRelationMenuInfo(Long menuId){
        List<SysMenuDTO> sysMenuDTOList = getByParentId(menuId);
        for (SysMenuDTO sysMenuDTO : sysMenuDTOList) {
            Long id = sysMenuDTO.getId();
            deleteRelationMenuInfo(id);
        }
        //删除当前菜单关系表
        sysRoleMenuRelationService.deleteByMenuId(menuId);
        //删除当前菜单
        deleteById(menuId);
    }

    /**
     * 根据菜单id获取子菜单信息
     * @param id 菜单id
     * @return
     */
    public List<SysMenuDTO> getByParentId(Long id){
        Wrapper<SysMenuDTO> wrapper = new EntityWrapper<>();
        wrapper.eq("parent_id",id);
        wrapper.eq("web_type",0);//0平台系统权限
        return selectList(wrapper);
    }

    /**
     * 获取商家的权限
     * @return
     */
    @Override
    public List<SysMenuDTO> getShopManagerMenuList(){
        return getMenuListByConfigCode(SYSCodeEnum.CONFIG_CODE_MANAGER.getMsg());
    }

    /**
     * 根据配置code获取菜单
     * @param code
     * @return
     */
    private List<SysMenuDTO> getMenuListByConfigCode(String code){
        SysConfigDTO sysConfigDTO = sysConfigService.getByCode(code);
        if(null == sysConfigDTO)
            throw new RuntimeException("没有这个角色信息");
        return sysMenuMapper.selectMenuInfoListByRoleId(Long.parseLong(sysConfigDTO.getValue()));
    }

    /**
     *
     * 根据多个角色的id获取菜单信息 取并集
     * @param roleIds
     * @return
     */
    @Override
    public List<SysMenuVO> getMenuListByRoleIds(List<Long> roleIds,boolean isAdmin){
        Set<Long> idSet = new HashSet<>();
        List<SysMenuVO> newMenuList = new ArrayList<>();
        List<SysMenuVO> sysMenuVOList = sysRoleMenuRelationMapper.selectListMenuVOByRoleId(roleIds);
        for (SysMenuVO sysMenuVO : sysMenuVOList) {
            //去除重复权限
            String code = sysMenuVO.getCode();
            if(StrUtils.isEmpty(code)){
                continue;
            }
            Set<String> codeSet = new HashSet<>(Arrays.asList(code.split(",")));
            sysMenuVO.setCode(codeSet.stream().collect(Collectors.joining(",")));
            if(!isAdmin){//不是admin
                Long parentId = sysMenuVO.getParentId();
                if(parentId == 0){
                   continue;
                }
                boolean f = idSet.add(parentId);
                if(f){//没有重复的
                    newMenuList.add((getVOById(sysMenuVO.getParentId())));
                }
            }
        }
        sysMenuVOList.addAll(newMenuList);
        return sysMenuVOList;
    }


    /**
     *
     * 根据单个角色id获取菜单信息
     * @param roleId
     * @return
     */
//    @Override
//    public List<SysMenuDTO> getMenuListByRoleId(Long roleId){
//        List<Long> menuList = selectMenuIdListByRoleId(roleId);
//        return getMenuInfoListByIds(menuList,SYSCodeEnum.IN_0.getCode());
//    }

    /**
     * 根据角色id获取下面的菜单Id
     * @param roleId
     * @return
     */
    @Override
    public List<Long> selectMenuIdListByRoleId(Long roleId){
        return sysMenuMapper.selectMenuIdListByRoleId(roleId);
    }

    /**
     * 根据角色id获取不属于自己下面的菜单Id
     * @param roleId
     * @return
     */
//    @Override
//    public List<SysMenuVO> selectMenuIdListNotMeByRoleId(Long roleId){
//        List<Long> ids = new ArrayList<>();
//        List<SysMenuVO> menuList = new ArrayList<>();
//        ids.add(roleId);
//        List<SysMenuDTO> sysMenuDTOList = getMenuInfoListByIds(ids, SYSCodeEnum.IN_0.getCode());
//        for (SysMenuDTO sysMenuDTO : sysMenuDTOList) {
//            SysMenuVO sysMenuVO = new SysMenuVO();
//            BeanUtils.copyProperties(sysMenuDTO,sysMenuVO);
//            menuList.add(sysMenuVO);
//        }
//        return builTree(menuList);
//    }

    /**
     * 根据角色id获取属于自己下面的菜单Id
     * @param roleId
     * @return
     */
    @Override
    public List<SysMenuVO> selectMenuIdListMeByRoleId(Long roleId){
        List<SysMenuVO> sysMenuVOS = sysRoleMenuRelationMapper.selectListMenuVOByRoleId(Arrays.asList(roleId));
        return sysMenuVOS;
    }

    /**
     * 根据角色id获取属于自己下面的菜单Id
     * @param roleId
     * @return
     */
    @Override
    public List<SysMenuDTO> selectListByRoleId(Long roleId){
        if(null == roleId){//查询所有的商家的权限
            Wrapper<SysMenuDTO> wrapper = new EntityWrapper<>();
            wrapper.eq("web_type", 1);
            wrapper.eq("menu", 0);
            return selectList(wrapper);
        }

        return sysRoleMenuRelationMapper.selectMenuListByRoleId(roleId);
    }

    @Override
    public SysMenuVO getVOById(Long id) {
        return baseMapper.getVOById(id);
    }


    //建立树形结构
    public List<SysMenuVO> builTree(List<SysMenuVO> menuList){
        List<SysMenuVO> treeMenus =new  ArrayList<>();
        for(SysMenuVO menuNode : getRootNode(menuList)) {
            menuNode=buildChilTree(menuNode,menuList);
            treeMenus.add(menuNode);
        }
        return treeMenus;
    }

    //递归，建立子树形结构
    private SysMenuVO buildChilTree(SysMenuVO pNode,List<SysMenuVO> menuList){
        List<SysMenuVO> chilMenus =new ArrayList<>();
        for(SysMenuVO menuNode : menuList) {
            if(menuNode.getParentId().equals(pNode.getId())) {
                chilMenus.add(buildChilTree(menuNode,menuList));
            }
        }
        pNode.setSysMenuVOList(chilMenus);
        return pNode;
    }

    //获取根节点
    private List<SysMenuVO> getRootNode(List<SysMenuVO> menuList) {
        List<SysMenuVO> rootMenuLists =new  ArrayList<>();
        for(SysMenuVO menuNode : menuList) {
            if(menuNode.getParentId().intValue() == 0) {
                rootMenuLists.add(menuNode);
            }
        }
        return rootMenuLists;
    }
}
